#include <string.h>
#include <stdio.h>
#include <stdint.h>

#include <holt.h>

//Tux the penguin, in 'holt' format.
static unsigned char tux[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
    0x0f, 0x3f, 0x3f, 0x77, 0x77, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x1f,
    0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xc1, 0x8f, 0x9f, 0x9e, 0xc4,
    0xe0, 0xfc, 0xfc, 0xf8, 0xc2, 0x9e, 0xcd, 0xe3,
    0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x03, 0x0f, 0x3f, 0xf3, 0xf7,
    0xef, 0xff, 0xfc, 0x00, 0x28, 0x08, 0x04, 0x16,
    0x02, 0x0b, 0x09, 0x09, 0x0b, 0x0f, 0x1c, 0xbc,
    0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0f,
    0x1f, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xf8,
    0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    0x80, 0xe0, 0xfe, 0x7f, 0x1f, 0x0e, 0x03, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0f, 0x7f, 0xff, 0xff, 0xff,
    0xe0, 0x9f, 0xff, 0xff, 0xf8, 0x80, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x80, 0xf0, 0xff, 0xff, 0xff,
    0x3f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xc0, 0xf8, 0xfc, 0xff, 0xff, 0xdf,
    0x5f, 0xbf, 0xdf, 0xde, 0x0c, 0x04, 0x07, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x03, 0xe7, 0xec, 0x98,
    0xf8, 0xf0, 0xf0, 0x70, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08,
    0x18, 0x30, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x80,
    0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xff, 0x03,
    0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
    0x7f, 0x7c, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x40, 0x40,
    0x40, 0x4f, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
    0x40, 0x40, 0x20, 0x20, 0x10, 0x18, 0x0c, 0x06,
    0x06, 0x03, 0x03, 0x03, 0x03, 0x07, 0xfe, 0xfc,
    0xc8, 0xf8, 0xf8, 0xf8, 0xf8, 0x78, 0x78, 0x78,
    0x78, 0x78, 0x78, 0x78, 0xf8, 0x88, 0x7c, 0xfc,
    0x06, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x06,
    0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10,
    0x10, 0x90, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void holt_lcd_clear (void) {
    unsigned int x, y;
    unsigned char report[HOLT_OUTPUT_USAGE_SIZE];
    
    memset(report, 0, sizeof(report));
    report[0] = 3;
    
    for (y = 0; y < 8; y++) {
        report[2] = y;
        for (x = 0; x < 0x80; x += 0xc) {
            report[3] = x;
            holt_write_report(report);
        }
    }
}

void holt_lcd_bitmap (const unsigned char *bitmap) {
    unsigned int x, y;
    unsigned char report[HOLT_OUTPUT_USAGE_SIZE];
    
    memset(report, 0, sizeof(report));
    report[0] = 3;
    
    for (y = 0; y < 8; y++, bitmap += HOLT_LCD_WIDTH) {
        report[2] = 7 - y;
        for (x = 0; x < 0x80; x += 0xc) {
            report[3] = x + 4;
            memcpy(&report[4], &bitmap[x], 0xc);
            holt_write_report(report);
        }
    }
}

void holt_lcd_tux (void) {
    holt_lcd_bitmap(tux);
}
    
void holt_lcd_convert_bitmap (const unsigned char *in, unsigned char *out) {
    unsigned char tmp[8];
    const unsigned char *tin;
    unsigned int y, x, t;

    for (y = 0; y < HOLT_LCD_HEIGHT; y += 8) {
        for (x = 0; x < HOLT_LCD_WIDTH; x += 8, out += 8) {
            //work backwards in the x direction
            tin = &in[((y+1) * HOLT_LCD_WIDTH - x - 8)/8];
            for (t = 0; t < 8; t++) {
                tmp[t] = tin[t * HOLT_LCD_WIDTH/8];
            }
            
            for (t = 0; t < 8; t++) {
                out[t]  = (tmp[0] & 1) << 7 | (tmp[1] & 1) << 6;
                out[t] |= (tmp[2] & 1) << 5 | (tmp[3] & 1) << 4;
                out[t] |= (tmp[4] & 1) << 3 | (tmp[5] & 1) << 2;
                out[t] |= (tmp[6] & 1) << 1 | (tmp[7] & 1) << 0;
                
                tmp[0] >>= 1; tmp[1] >>= 1; tmp[2] >>= 1; tmp[3] >>= 1;
                tmp[4] >>= 1; tmp[5] >>= 1; tmp[6] >>= 1; tmp[7] >>= 1;
            }
        }
    }
}

void holt_lcd_convert_bytemap (const unsigned char *in, unsigned char *out) {
    unsigned char tmp;
    const unsigned char *tin;
    unsigned int y, x;

    for (y = 0; y < HOLT_LCD_HEIGHT; y += 8) {
        for (x = 0; x < HOLT_LCD_WIDTH; x++, out++) {
            //work backwards
            tin = &in[(y+1) * HOLT_LCD_WIDTH - x - 1];
            
            //if (tin[foo] >= 0x80) tmp |= bit
            tmp  = (tin[0 * HOLT_LCD_WIDTH] & 0x80) >> 0;
            tmp |= (tin[1 * HOLT_LCD_WIDTH] & 0x80) >> 1;
            tmp |= (tin[2 * HOLT_LCD_WIDTH] & 0x80) >> 2;
            tmp |= (tin[3 * HOLT_LCD_WIDTH] & 0x80) >> 3;
            tmp |= (tin[4 * HOLT_LCD_WIDTH] & 0x80) >> 4;
            tmp |= (tin[5 * HOLT_LCD_WIDTH] & 0x80) >> 5;
            tmp |= (tin[6 * HOLT_LCD_WIDTH] & 0x80) >> 6;
            tmp |= (tin[7 * HOLT_LCD_WIDTH] & 0x80) >> 7;
            
            *out = tmp;
        }
    }
}

